#ifndef graymophologyH
#define graymophologyH

#include "Image.H"
#include "IO.H"
#include "Util.H"



void discStructureElement(pip::Image<unsigned char> &imOut, int rad){

     pip::Dimension dim(2*rad+1,2*rad+1); // dimensions of SE --> +1 for center
     imOut.resize(dim);
     int rad2 = rad*rad;
     int val;
     for (int y=0; y<=rad; ++y){
        for (int x=0; x<=rad; ++x){
          val = 0;

          if( (x*x+y*y) < rad2+0.5)
              val = 1;

          imOut(rad+x,rad+y) = val;
          imOut(rad-x,rad+y) = val;
          imOut(rad-x,rad-y) = val;
          imOut(rad+x,rad-y) = val;
      }
	}
}

template <class Tin>
void grayDilate(const pip::Image<Tin> &imIn, pip::Image<Tin> &imOut, const pip::Image<unsigned char> &se){
        // make sure we have the correct output size
        if (imOut.dimension()!= imIn.dimension()) {
                imOut.resize(imIn.dimension());
        }

        int iSEWidth  = se.dim(0);
        int iSECenter = iSEWidth/2;
        int iWidth    = imIn.dim(0);
        int iHeight   = imIn.dim(1);

        int iX, iY;
        // over all image pixels
        for (int y=0; y<iHeight; ++y)
        for (int x=0; x<iWidth; ++x) {
                imOut(x,y) = imIn(x,y);
                // over all se pixels
                for (int m=0; m<iSEWidth; ++m)
                for (int n=0; n<iSEWidth; ++n) {
                        if (se(n,m) > 0) {
                                iX = x+(m-iSECenter);
                                iY = y+(n-iSECenter);
                                if ( iX >= 0 && iX < iWidth && iY >= 0 && iY < iHeight)
                                imOut(x, y) = max(imOut(x,y),imIn(iX,iY));
                        }
                }
        }
}

template <class Tin>
void grayErode(const pip::Image<Tin> &imIn, pip::Image<Tin> &imOut, const pip::Image<unsigned char> &se){
        // make sure we have the correct output size
        if (imOut.dimension()!= imIn.dimension()) {
                imOut.resize(imIn.dimension());
        }

        int iSEWidth  = se.dim(0);
        int iSECenter = iSEWidth/2;
        int iWidth    = imIn.dim(0);
        int iHeight   = imIn.dim(1);

        int iX, iY;
        // over all image pixels
        for (int y=0; y<iHeight; ++y)
        for (int x=0; x<iWidth; ++x) {
                imOut(x,y) = imIn(x,y);
                // over all se pixels
                for (int m=0; m<iSEWidth; ++m)
                for (int n=0; n<iSEWidth; ++n) {
                        if (se(n,m) > 0) {
                                iX = x+(m-iSECenter);
                                iY = y+(n-iSECenter);
                                if ( iX >= 0 && iX < iWidth && iY >= 0 && iY < iHeight)
                                imOut(x, y) = min(imOut(x,y),imIn(iX,iY));
                        }
                }
        }
}

template <class Tin>
void grayOpening(const pip::Image<Tin> &imIn, pip::Image<Tin> &imOut, const pip::Image<unsigned char> &se){
        grayErode(imIn, imOut,se);
        pip::Image<Tin> tmpCopy(imOut);
        grayDilate(tmpCopy, imOut,se);
}

template <class Tin>
void grayClosing(const pip::Image<Tin> &imIn, pip::Image<Tin> &imOut, const pip::Image<unsigned char> &se){
        grayDilate(imIn, imOut,se);
        pip::Image<Tin> tmpCopy(imOut);
        grayErode(tmpCopy, imOut,se);
}
#endif